#include <string.h>
#include <sys/time.h>

#include "TFly_list.h"
#include "script_block.h"
#include "script_expression.h"
#include "script_func.h"
#include "script_include.h"
#include "script_keyword.h"
#include "script.h"
#include "script_debug.h"
#include "script_memory.h"
#include "script_string.h"
#include "script_var.h"

static struct for_data *for_data_create(script_t *script)
{
	struct for_data *data = script_calloc(1,sizeof(struct for_data));
	data->block = script_code_block_create(script);	
	data->block->type = SCRIPT_BLOCK_TYPE_LOOP;
	return data;
}

static void for_data_destroy(struct for_data *data)
{
	if(data == NULL){
		return;
	}

	if(data->block){
		script_code_block_destroy(data->block);
	}
	if(data->key){
		exp_node_destroy(data->key);
	}
	if(data->value){
		exp_node_destroy(data->value);
	}
	if(data->src){
		exp_node_list_destroy(data->src);
	}
	script_free(data);
}

static int var_parse(const struct script_keyword_t *keyword,struct exp_string_t *exp_str, script_t *script)
{
	int ret = SCRIPT_ERR_NONE;
	struct exp_string_t *name = exp_str;
	struct exp_string_t *tmp = exp_str->next;
	script_code_block_t *block = script_stack_Top(script->code_stack);
	if(block == NULL){
		return SCRIPT_ERR_PARAM;
	}
	exp_var_t *var = exp_var_struct_get_var(block->vars,name->str);
	if(var){
		SCRIPT_DEBUG_ERR("var: %s is exist",name->str);
		return SCRIPT_ERR_VAR_DEFINE;
	}

	// 把变量添加到block的变量列表中  block解析完成后清除
	exp_var_struct_add_parse(block->vars,name->str,NULL);

	exp_node_t *exp = NULL;
	exp_node_t *arg = NULL;

	// 创建一个内置C函数执行节点
	exp = exp_node_create(EXP_NODE_TYPE_FUNC,NULL);
	exp->func = script_func_node_create();
	if(exp->func == NULL){
		ret = SCRIPT_ERR_MEMORY;
		goto err;
	}
	exp->func->exp = &keyword->keyword_func;

	// 解析"创建变量"函数的参数
	if(tmp == NULL){	// 定义一个空变量
		arg = exp_node_create(EXP_NODE_TYPE_VAR_NAME,name->str);
	}else{				// 变量赋初值
		if(strcmp(tmp->str,"=") != 0 && 
				strcmp(tmp->str,"=>") != 0){
			SCRIPT_DEBUG_ERR("syntax err");
			ret = SCRIPT_ERR_SYNTAX;
			goto err;
		}

		tmp = tmp->next;
		if(tmp == NULL){
			ret = SCRIPT_ERR_SYNTAX;
			goto err;
		}

		arg = expression_decode(name,script);
		if(arg == NULL){
			// TODO 
		}

	}

	// 给"创建变量"函数添加参数
	TFly_list_add(exp->func->args,arg);

	// 把“创建变量”函数语句加入代码块
	TFly_list_add(block->exp_list,script_exp_create(script->line,exp));

	return ret;
err:
	if(exp){
		if(exp->func){
			// TODO
			script_func_node_destroy(exp->func);
		}
		exp_node_destroy(exp);
	}

	if(arg){
		exp_node_destroy(arg);
	}
	return ret;
}

static script_func_t *script_func_create(char *name,script_t *script)
{
	if(name == NULL || strlen(name) == 0){
		return NULL;
	}

	script_func_t *func = script_calloc(1,sizeof(script_func_t) + strlen(name) + 1);
	if(func == NULL){
		return NULL;
	}

	func->name = (char*)func + sizeof(script_func_t);
	strcpy(func->name,name);

	func->block = script_code_block_create(script);
	func->block->type = SCRIPT_BLOCK_TYPE_FUNC;
	func->args = TFly_list_create();

	return func;
}

void script_func_destroy(script_func_t *func)
{
	if(func == NULL){
		return;
	}

	if(func->block){
		script_code_block_destroy(func->block);
	}

	if(func->args){
		exp_node_t *node = TFly_list_del_first(func->args);
		while(node){
			exp_node_list_destroy(node);
			node = TFly_list_del_first(func->args);
		}
		TFly_list_destroy(func->args);
	}

	script_free(func);
}


/********************************************************
 *	脚本函数定义解析
 *
 * ******************************************************/
static int script_func_parse(const struct script_keyword_t *keyword,struct exp_string_t *exp_str, script_t *script)
{
	if(exp_str == NULL || exp_str->next == NULL){
		return SCRIPT_ERR_SYNTAX;
	}

	//show_exp_string_t(exp_str);

	exp_string_t *name = exp_str;

	exp_string_t *tmp = exp_str->next;

	if(strcmp(tmp->str,"(") != 0){
		return SCRIPT_ERR_SYNTAX;
	}
	tmp = tmp->next;

	exp_var_t *fv = exp_var_struct_get_var(script->exec_block->vars,name->str);
	if(fv){
		SCRIPT_DEBUG_ERR("multiply defined function %s",name->str);
		return SCRIPT_ERR_SYNTAX;
	}

	script_func_t *func = script_func_create(name->str,script);
	func->exec_block= script->exec_block;

	int param_done = 0;
	while(tmp){
		//printf("%s %d tmp:%s\n",__func__,__LINE__,tmp->str);
		if(strcmp(tmp->str,")") == 0){
			param_done = 1;
		}else if(strcmp(tmp->str,"{") == 0){
			if(param_done == 0){
				goto syntax_err;
			}
			exp_func_t *exp_func = script_calloc(1,sizeof(exp_func_t));
			exp_func->type = EXEC_FUNC_TYPE_SCRIPT;
			exp_func->s_func = func;


			TFly_list_add(script->funcs,exp_func);
			exp_var_t *var = exp_var_create(func->name);
			var->type = EXP_VAR_TYPE_FUNCTION;
			var->func = exp_var_func_create(exp_func,script->exec_block);
			exp_var_struct_add(script->exec_block->vars,var);

			script_stack_Push(script->code_stack,func->block);
		}else if(strcmp(tmp->str,",") == 0){

		}else{
			exp_var_struct_add_parse(func->block->vars,tmp->str,NULL); // block 解析完成后清除。 用于解析时变量查重
			exp_node_t *arg = exp_node_create(EXP_NODE_TYPE_CONST_STRING,tmp->str);
			TFly_list_add(func->args,arg);
		}

		tmp = tmp->next;
	}

	return SCRIPT_ERR_NONE;

syntax_err:

	if(func){
		script_func_destroy(func);
	}
	return SCRIPT_ERR_SYNTAX;

}


static int include_parse(const struct script_keyword_t *keyword,struct exp_string_t *exp_str, script_t *script)
{
	if(exp_str == NULL || exp_str->next == NULL){
		return SCRIPT_ERR_SYNTAX;
	}

	int ret = SCRIPT_ERR_NONE;

	exp_string_t *tmp = exp_str;

	if(strcmp(tmp->str,"(") != 0){
		return SCRIPT_ERR_SYNTAX;
	}
	exp_string_t *file_name = tmp->next;

	tmp = file_name->next;
	if(tmp == NULL){
		return SCRIPT_ERR_SYNTAX;
	}

	script_t *load = NULL;

	if(tmp->str[0] == ')'){
		int len = strlen(file_name->str);
		char *name = script_calloc(1,strlen(file_name->str));
		memcpy(name,file_name->str+1,len-2);

		if(script_parse_from_file(script,name)){
			SCRIPT_DEBUG_ERR("Load file %s fail",file_name->str);
			ret = SCRIPT_ERR_PARAM;
			script_free(name);
			goto err;
		}
		script_free(name);
	}else{
		script_stack_t *stack = script_stack_create(1);
		exp_parser_t parser = {0};
		parser.stack = stack;
		parser.strs = file_name;
		parser.c_str = file_name;
		parser.script = script;
		parser.exec_func_arg_flag = 1;

		if(expression_str(&parser) < 0){
			script_stack_destroy(stack);
			ret = SCRIPT_ERR_SYNTAX;
			goto err;
		}

		exp_node_t *exp = exp_node_create(EXP_NODE_TYPE_FUNC,NULL);
		exec_func_t *func = script_func_node_create();
		func->exp = &keyword->keyword_func;
		exp->func = func;
		script_code_block_t *block = script_stack_Top(script->code_stack);
		TFly_list_add(block->exp_list,script_exp_create(script->line,exp));

		// include_func 第一个变量为父script指针
		TFly_list_add(func->args,script);

		// include_func 第二个变量为文件路径表达式
		TFly_list_add(func->args,parser.exp_list);
		
		// include_func 第三个变量为加载后的变量名
		exp_parser_t nparser;
		memset(&nparser,0,sizeof(nparser));
		nparser.stack = stack;
		nparser.c_str = parser.c_str;
		nparser.strs = parser.c_str;
		nparser.exec_func_arg_flag = 1;
		nparser.script = script;

		if(expression_str(&nparser) < 0){
			script_stack_destroy(stack);
			ret = SCRIPT_ERR_SYNTAX;
			goto err;
		}
		TFly_list_add(func->args,nparser.exp_list);

		//exp = exp_node_create(EXP_NODE_TYPE_CONST_STRING,parser.c_str->str);
		//TFly_list_add(func->args,exp);

		script_stack_destroy(stack);

	}

err:
	if(load){
		script_destroy(load);
	}
	return ret;
}

static void include_destroy(exec_func_t *func)
{
	if(func == NULL){
		return;
	}

	if(func->args){
		//script_include_t *inc = TFly_list_del_first(func->args);
		//script_include_destroy(inc);
		//exp_node_t *node = TFly_list_del_first(func->args);
		//exp_node_destroy(node);
		
		TFly_list_del_first(func->args);

		exp_node_t *node = TFly_list_del_first(func->args);
		exp_node_list_destroy(node);

		node = TFly_list_del_first(func->args);
		exp_node_list_destroy(node);

		TFly_list_destroy(func->args);
	}
	
	script_free(func);
}

static int if_parse(const struct script_keyword_t *keyword,struct exp_string_t *exp_str, script_t *script)
{
	exp_string_t *tmp = exp_str;
	if(strcmp(tmp->str,"(") != 0){
		return SCRIPT_ERR_SYNTAX;
	}
	exp_string_t *prev = tmp;
	tmp = tmp->next;
	while(tmp){
		if(strcmp(tmp->str,"{") == 0){
			prev->next = NULL;
			exp_string_destroy(tmp);
			break;
		}
		prev = tmp;
		tmp = tmp->next;
	}

	struct if_data *data = script_calloc(1,sizeof(struct if_data));

	script_stack_t *stack = script_stack_create(1);

	exp_parser_t parser = {0};
	parser.stack = stack;
	parser.strs = exp_str;
	parser.c_str = exp_str;
	parser.script = script;

	if(expression_str(&parser) < 0){
		// TODO error handle
		script_stack_destroy(stack);
		goto syntax_err;
	}
	script_stack_destroy(stack);

	data->exp = parser.exp_list;
	data->block = script_code_block_create(script);

	exp_node_t *exp = exp_node_create(EXP_NODE_TYPE_FUNC,NULL);
	exec_func_t *func = script_func_node_create();
	func->exp = &keyword->keyword_func;
	TFly_list_add(func->args,data);

	exp->func = func;

	script_code_block_t *block = script_stack_Top(script->code_stack);
	TFly_list_add(block->exp_list,script_exp_create(script->line,exp));


	script_stack_Push(script->code_stack,data->block);


	return SCRIPT_ERR_NONE;

syntax_err:
	return SCRIPT_ERR_SYNTAX;
}

static void if_data_destroy(struct if_data *data)
{
	if(data == NULL){
		return;
	}

	if(data->block){
		script_code_block_destroy(data->block);
	}
	if(data->exp){
		exp_node_list_destroy(data->exp);
	}

	script_free(data);
}

static void if_destroy(exec_func_t *func)
{
	if(func == NULL){
		return;
	}

	if(func->args){
		struct if_data *data = TFly_list_del_first(func->args);
		while(data){
			if_data_destroy(data);
			data = TFly_list_del_first(func->args);
		}
		TFly_list_destroy(func->args);
	}
	
	script_free(func);
}

static int elif_parse(const struct script_keyword_t *keyword,struct exp_string_t *exp_str, script_t *script)
{
	exp_string_t *tmp = exp_str;
	if(strcmp(tmp->str,"(") != 0){
		return SCRIPT_ERR_SYNTAX;
	}
	exp_string_t *prev = tmp;
	tmp = tmp->next;
	while(tmp){
		if(strcmp(tmp->str,"{") == 0){
			prev->next = NULL;
			exp_string_destroy(tmp);
			break;
		}
		prev = tmp;
		tmp = tmp->next;
	}

	script_code_block_t *block = script_stack_Top(script->code_stack);

	script_exp_t *st = TFly_list_get_end(block->exp_list);
	exp_node_t *exp = st->exp;
	if(exp == NULL){
		return SCRIPT_ERR_SYNTAX;	
	}
	if(exp->type != EXP_NODE_TYPE_FUNC){
		return SCRIPT_ERR_SYNTAX;	
	}
	if(exp->func->exp != &keyword->keyword_func){
		//return SCRIPT_ERR_SYNTAX;
	}

	struct if_data *data = script_calloc(1,sizeof(struct if_data));

	script_stack_t *stack = script_stack_create(1);

	exp_parser_t parser = {0};
	parser.stack = stack;
	parser.strs = exp_str;
	parser.c_str = exp_str;
	parser.script = script;

	if(expression_str(&parser) < 0){
		// TODO error handle
		script_stack_destroy(stack);
		goto syntax_err;
	}

	script_stack_destroy(stack);

	data->exp = parser.exp_list;
	data->block = script_code_block_create(script);

	TFly_list_add(exp->func->args,data);

	script_stack_Push(script->code_stack,data->block);


	return SCRIPT_ERR_NONE;

syntax_err:
	return SCRIPT_ERR_SYNTAX;
}

static int else_parse(const struct script_keyword_t *keyword,struct exp_string_t *exp_str, script_t *script)
{

	if(exp_str == NULL || exp_str->str[0] != '{'){
		return SCRIPT_ERR_SYNTAX;
	}

	script_code_block_t *block = script_stack_Top(script->code_stack);

	script_exp_t *st = TFly_list_get_end(block->exp_list);
	exp_node_t *exp = st->exp;
	if(exp == NULL){
		return SCRIPT_ERR_SYNTAX;	
	}
	if(exp->type != EXP_NODE_TYPE_FUNC){
		return SCRIPT_ERR_SYNTAX;	
	}
	if(exp->func->exp != &keyword->keyword_func){
		//return SCRIPT_ERR_SYNTAX;
	}

	struct if_data *data = script_calloc(1,sizeof(struct if_data));


	data->exp = exp_node_create(EXP_NODE_TYPE_CONST_INT,(void*)1);
	data->block = script_code_block_create(script);

	TFly_list_add(exp->func->args,data);


	script_stack_Push(script->code_stack,data->block);


	return SCRIPT_ERR_NONE;
}

static int while_parse(const struct script_keyword_t *keyword,struct exp_string_t *exp_str, script_t *script)
{
	exp_string_t *tmp = exp_str;
	if(strcmp(tmp->str,"(") != 0){
		return SCRIPT_ERR_SYNTAX;
	}
	exp_string_t *prev = tmp;
	tmp = tmp->next;
	while(tmp){
		if(strcmp(tmp->str,"{") == 0){
			prev->next = NULL;
			exp_string_destroy(tmp);
			break;
		}
		prev = tmp;
		tmp = tmp->next;
	}

	struct if_data *data = script_calloc(1,sizeof(struct if_data));

	script_stack_t *stack = script_stack_create(1);

	exp_parser_t parser = {0};
	parser.stack = stack;
	parser.strs = exp_str;
	parser.c_str = exp_str;
	parser.script = script;

	if(expression_str(&parser) < 0){
		// TODO error handle
		script_stack_destroy(stack);
		goto syntax_err;
	}
	script_stack_destroy(stack);

	data->exp = parser.exp_list;
	data->block = script_code_block_create(script);
	data->block->type = SCRIPT_BLOCK_TYPE_LOOP;

	exp_node_t *exp = exp_node_create(EXP_NODE_TYPE_FUNC,NULL);
	exec_func_t *func = script_func_node_create();
	func->exp = &keyword->keyword_func;
	TFly_list_add(func->args,data);

	exp->func = func;

	script_code_block_t *block = script_stack_Top(script->code_stack);
	TFly_list_add(block->exp_list,script_exp_create(script->line,exp));


	script_stack_Push(script->code_stack,data->block);


	return SCRIPT_ERR_NONE;

syntax_err:
	return SCRIPT_ERR_SYNTAX;
}

static int for_parse(const struct script_keyword_t *keyword,struct exp_string_t *exp_str, script_t *script)
{
	exp_string_t *value = exp_str;
	if(value->type != EXP_STRING_TYPE_STRING){
		return SCRIPT_ERR_SYNTAX;
	}
	exp_string_t *in = value->next;
	exp_string_t *key = NULL;
	if(in->type == EXP_STRING_TYPE_OPERTOR && strcmp(in->str,",") == 0){
		key = in->next;
		in = key->next;
	}

	if(in->type != EXP_STRING_TYPE_STRING || 
			strcmp(in->str,"in") != 0){
		return SCRIPT_ERR_SYNTAX;
	}

	exp_string_t *src= in->next;
	if(src == NULL){
		return SCRIPT_ERR_SYNTAX;
	}

	exp_string_t *tmp,*prev;
	prev = src;
	tmp = src->next;
	while(tmp){
		if(tmp->str[0] == '{'){
			exp_string_destroy(tmp);
			prev->next = NULL;
			break;
		}
		prev = tmp;
		tmp = tmp->next;
	}


	struct for_data *data = for_data_create(script);

	script_stack_t *stack = script_stack_create(1);

	exp_parser_t parser = {0};
	parser.stack = stack;
	parser.strs = exp_str;
	parser.c_str = src;
	parser.script = script;

	if(expression_str(&parser) < 0){
		// TODO error handle
		script_stack_destroy(stack);
		goto syntax_err;
	}
	script_stack_destroy(stack);

	data->src = parser.exp_list;
	data->value = exp_node_create(EXP_NODE_TYPE_CONST_STRING,value->str);
	if(key){
		data->key = exp_node_create(EXP_NODE_TYPE_CONST_STRING, key->str);
	}

	exp_node_t *exp = exp_node_create(EXP_NODE_TYPE_FUNC,NULL);
	exec_func_t *func = script_func_node_create();
	func->exp = &keyword->keyword_func;
	TFly_list_add(func->args,data);

	exp->func = func;

	script_code_block_t *block = script_stack_Top(script->code_stack);
	TFly_list_add(block->exp_list,script_exp_create(script->line,exp));

	exp_var_struct_add_parse(data->block->vars,value->str,NULL);
	script_stack_Push(script->code_stack,data->block);


	return SCRIPT_ERR_NONE;

syntax_err:
	for_data_destroy(data);
	return SCRIPT_ERR_SYNTAX;
}

static void for_destroy(exec_func_t *func)
{
	if(func == NULL){
		return;
	}

	if(func->args){
		struct for_data *data = TFly_list_del_first(func->args);
		for_data_destroy(data);
		TFly_list_destroy(func->args);
	}
	
	script_free(func);
}

static int return_parse(const struct script_keyword_t *keyword,struct exp_string_t *exp_str, script_t *script)
{
	int ret = SCRIPT_ERR_NONE;
	exp_node_t *exp = NULL;
	exp_node_t *arg = NULL;

	script_code_block_t *block = script_stack_Top(script->code_stack);

	// 创建一个内置C函数执行节点
	exp = exp_node_create(EXP_NODE_TYPE_FUNC,NULL);
	exp->func = script_func_node_create();
	if(exp->func == NULL){
		ret = SCRIPT_ERR_MEMORY;
		goto err;
	}
	exp->func->exp = &keyword->keyword_func;

	// 解析"创建变量"函数的参数
	if(exp_str){				// 变量赋初值
		arg = expression_decode(exp_str,script);
		if(arg == NULL){
			// TODO 
			ret = SCRIPT_ERR_SYNTAX;
			goto err;
		}

		// 给"创建变量"函数添加参数
		TFly_list_add(exp->func->args,arg);
	}

	// 把“创建变量”函数语句加入代码块
	TFly_list_add(block->exp_list,script_exp_create(script->line,exp));
	return ret;

err:
	return ret;

}

static int break_parse(const struct script_keyword_t *keyword,struct exp_string_t *exp_str, script_t *script)
{
	int ret = SCRIPT_ERR_NONE;
	exp_node_t *exp = NULL;

	script_code_block_t *block;

	int i = -1;
	block = script_stack_get(script->code_stack,i);
	while(block){
		if(block->type == SCRIPT_BLOCK_TYPE_LOOP){
			break;
		}else if(block->type == SCRIPT_BLOCK_TYPE_FUNC){
			SCRIPT_DEBUG_ERR("break isn't in a loop block");
			return SCRIPT_ERR_SYNTAX;
		}
		i--;
		block = script_stack_get(script->code_stack,i);
	}
	if(block == NULL){
		SCRIPT_DEBUG_ERR("break isn't in a loop block");
		return SCRIPT_ERR_SYNTAX;
	}

	block = script_stack_Top(script->code_stack);

	// 创建一个内置C函数执行节点
	exp = exp_node_create(EXP_NODE_TYPE_FUNC,NULL);
	exp->func = script_func_node_create();
	if(exp->func == NULL){
		ret = SCRIPT_ERR_MEMORY;
		goto err;
	}
	exp->func->exp = &keyword->keyword_func;

	TFly_list_add(block->exp_list,script_exp_create(script->line,exp));
	return ret;

err:
	return ret;

}

static int continue_parse(const struct script_keyword_t *keyword,struct exp_string_t *exp_str, script_t *script)
{
	int ret = SCRIPT_ERR_NONE;
	exp_node_t *exp = NULL;

	script_code_block_t *block;
	int i = -1;
	block = script_stack_get(script->code_stack,i);
	while(block){
		if(block->type == SCRIPT_BLOCK_TYPE_LOOP){
			break;
		}else if(block->type == SCRIPT_BLOCK_TYPE_FUNC){
			SCRIPT_DEBUG_ERR("continue isn't in a loop block");
			return SCRIPT_ERR_SYNTAX;
		}
		i--;
		block = script_stack_get(script->code_stack,i);
	}
	if(block == NULL){
		SCRIPT_DEBUG_ERR("continue isn't in a loop block");
		return SCRIPT_ERR_SYNTAX;
	}

	block = script_stack_Top(script->code_stack);

	// 创建一个内置C函数执行节点
	exp = exp_node_create(EXP_NODE_TYPE_FUNC,NULL);
	exp->func = script_func_node_create();
	if(exp->func == NULL){
		ret = SCRIPT_ERR_MEMORY;
		goto err;
	}
	exp->func->exp = &keyword->keyword_func;

	TFly_list_add(block->exp_list,script_exp_create(script->line,exp));
	return ret;

err:
	return ret;

}

static exp_node_t *create_var(TFly_list_t *args, script_stack_t *block_stack,void *param)
{
	if(args == NULL || block_stack == NULL){
		return NULL;
	}

	script_exec_block_t *block = script_stack_Top(block_stack);

	if(block == NULL){
		return NULL;
	}

	exp_node_t *node = TFly_list_get_first(args);

	if(node == NULL || node->type != EXP_NODE_TYPE_VAR_NAME){
		return NULL;
	}
	exp_var_t *var = exp_var_create(node->var_name);
	exp_var_struct_add(block->vars,var);

	exp_node_t *result = expression_calc(node,block_stack);
	
	return result;
}

static exp_node_t *sn_return(TFly_list_t *args, script_stack_t *block_stack,void *param)
{
	exp_node_t *arg = TFly_list_get_first(args);

	exp_node_t *result;
	if(arg){
		result = expression_calc(arg,block_stack);
		if(result == NULL || result->type == EXP_NODE_TYPE_ERR){
			exp_node_destroy(result);
			SCRIPT_DEBUG_ERR("return fail");
			exp_node_create(EXP_NODE_TYPE_ERR,NULL);
		}
		exp_node_type_e type;
		int num;
		char *str;
		double d;
		get_exp_node_value(result,&type,&str,&num,&d);
		if(type == EXP_NODE_TYPE_VAR){
			exp_node_t *new = exp_node_create(EXP_NODE_TYPE_VAR,NULL);
			new->var = exp_var_refer(result->var);
			new->ctrl = EXP_NODE_CTRL_RETURN;
			exp_node_destroy(result);
			return new;
		}else if(type == EXP_NODE_TYPE_CONST_INT){
			exp_node_t *new = exp_node_create(EXP_NODE_TYPE_CONST_INT,(void*)num);
			exp_node_destroy(result);
			result = new;
		}else if(type == EXP_NODE_TYPE_CONST_STRING){
			exp_node_t *new = exp_node_create(EXP_NODE_TYPE_CONST_STRING,str);
			exp_node_destroy(result);
			result = new;
		}else if(type == EXP_NODE_TYPE_CONST_DOUBLE){
			exp_node_t *new = exp_node_create(EXP_NODE_TYPE_CONST_DOUBLE,&d);
			exp_node_destroy(result);
			result = new;
		}else{
			exp_node_t *new = exp_node_create(type,NULL);
			exp_node_destroy(result);
			result = new;
		}
	}else{
		result = exp_node_create(EXP_NODE_TYPE_CONST_NULL,NULL);

	}

	result->ctrl = EXP_NODE_CTRL_RETURN;
	return result;
}

static exp_node_t *sn_break(TFly_list_t *args, script_stack_t *block_stack,void *param)
{
	exp_node_t *result;
	result = exp_node_create(EXP_NODE_TYPE_CONST_NULL,NULL);

	result->ctrl = EXP_NODE_CTRL_BREAK;
	return result;
}

static exp_node_t *sn_continue(TFly_list_t *args, script_stack_t *block_stack,void *param)
{
	exp_node_t *result;
	result = exp_node_create(EXP_NODE_TYPE_CONST_NULL,NULL);

	result->ctrl = EXP_NODE_CTRL_CONTINUE;
	return result;
}

static exp_node_t *if_func(TFly_list_t *args, script_stack_t *block_stack,void *param)
{
	if(args == NULL || block_stack == NULL){
		return NULL;
	}

	struct if_data *data;
	data = TFly_list_get_first(args);
	while(data){
		exp_node_t *result = expression_calc(data->exp,block_stack);
		if(result == NULL){
			SCRIPT_DEBUG_ERR("if exec fail");
			return exp_node_create(EXP_NODE_TYPE_ERR,NULL);
		}
		if(result->type == EXP_NODE_TYPE_ERR){
			return result;
		}


		if(judge(result)){
			exp_node_destroy(result);
			result = run_block(data->block,block_stack,NULL);
			return result;
		}
		exp_node_destroy(result);
		data = TFly_list_get_next(args);
	}

	return exp_node_create(EXP_NODE_TYPE_CONST_NULL,NULL);

}

static exp_node_t *while_func(TFly_list_t *args, script_stack_t *block_stack,void *param)
{
	if(args == NULL || block_stack == NULL){
		return NULL;
	}

	struct if_data *data;
	data = TFly_list_get_first(args);
	exp_node_t *res = NULL;

	while(1){
		exp_node_t *result = expression_calc(data->exp,block_stack);
		if(result == NULL){
			SCRIPT_DEBUG_ERR("while exec fail");
			return exp_node_create(EXP_NODE_TYPE_ERR,NULL);
		}
		if(result->type == EXP_NODE_TYPE_ERR){
			return result;
		}
		if(judge(result)){
			exp_node_destroy(result);
			res = run_block(data->block,block_stack,NULL);
			if(res->ctrl == EXP_NODE_CTRL_BREAK){
				exp_node_destroy(res);
				res = NULL;
				break;
			}else if(res->ctrl == EXP_NODE_CTRL_CONTINUE){

			}else if(res->ctrl == EXP_NODE_CTRL_RETURN){
				break;
			}
			exp_node_destroy(res);
			res = NULL;
		}else{
			exp_node_destroy(result);
			break;
		}
	}

	if(res){
		return res;
	}else{
		return exp_node_create(EXP_NODE_TYPE_CONST_NULL,NULL);
	}
}

exp_node_t *for_func(TFly_list_t *args, script_stack_t *block_stack,void *param)
{
	if(args == NULL || block_stack == NULL){
		return NULL;
	}

	struct for_data *data;
	data = TFly_list_get_first(args);

	exp_node_t *value = expression_calc(data->src,block_stack);
	if(value == NULL || value->type == EXP_NODE_TYPE_ERR){
		exp_node_destroy(value);
		return exp_node_create(EXP_NODE_TYPE_ERR,NULL);
	}

	if(value->type != EXP_NODE_TYPE_VAR){
		SCRIPT_DEBUG_WARN("for value type invalid");
		exp_node_destroy(value);
		return exp_node_create(EXP_NODE_TYPE_ERR,NULL);
	}

	exp_var_t *arr = exp_var_point_take(value->var);
	if(arr == NULL || 
			(arr->type != EXP_VAR_TYPE_ARRAY && 
			 arr->type != EXP_VAR_TYPE_STRUCT)){
		SCRIPT_DEBUG_WARN("for value type invalid");
		exp_node_destroy(value);
		return exp_node_create(EXP_NODE_TYPE_ERR,NULL);
	}


	int count = 0;
	TFly_list_item_t item = {0};
	exp_var_t *var = NULL;

	exp_node_t *res = NULL;



	
	if(arr->type == EXP_VAR_TYPE_ARRAY){
		if(!arr->array || arr->array->len == 0){
			goto exit;
		}

		exp_var_t *new = exp_var_create(data->value->string);
		new->type = EXP_VAR_TYPE_POINT;

		exp_var_t *key = NULL;
		if(data->key){
			key = exp_var_create(data->key->string);
			key->type = EXP_VAR_TYPE_INT;
		}

		int len = arr->array->len;
		exp_var_t **p = script_calloc(sizeof(exp_var_t*),len);
		memcpy(p,arr->array->p,len*sizeof(exp_var_t*));
		for(count = 0; count < len; count++){
			var = p[count];
			exp_var_destroy(new->var);
			new->var = exp_var_refer(var);

			if(data->key){
				key->value = count;
			}

			exp_var_t *vars = exp_var_create(NULL);
			vars->type = EXP_VAR_TYPE_STRUCT;
			exp_var_struct_add(vars,exp_var_refer(new));
			exp_var_struct_add(vars,exp_var_refer(key));

			res = run_block(data->block,block_stack,vars);
			if(res->ctrl == EXP_NODE_CTRL_BREAK){
				exp_node_destroy(res);
				res = NULL;
				break;
			}else if(res->ctrl == EXP_NODE_CTRL_CONTINUE){

			}else if(res->ctrl == EXP_NODE_CTRL_RETURN){
				break;
			}
			exp_node_destroy(res);
			res = NULL;
		}
		exp_var_destroy(new);
		exp_var_destroy(key);
		script_free(p);
	}else if(arr->object){
		var = TFly_list_item_get(&arr->object->children,&item);
		while(var){
			exp_var_t *next;
			next = TFly_list_item_get(&arr->object->children,&item);


			exp_var_t *new = exp_var_create(data->value->string);
			new->type = EXP_VAR_TYPE_POINT;
			new->var = exp_var_refer(var);


			exp_var_t *vars = exp_var_create(NULL);
			vars->type = EXP_VAR_TYPE_STRUCT;
			exp_var_struct_add(vars,new);

			if(data->key){
				exp_var_t *new = exp_var_create(data->key->string);
				if(var->name){
					new->type = EXP_VAR_TYPE_STRING;
					new->str = script_calloc(1,strlen(var->name)+1);
					strcpy(new->str,var->name);
				}else{
					new->type = EXP_VAR_TYPE_NONE;
				}
				exp_var_struct_add(vars,new);
			}


			res = run_block(data->block,block_stack,vars);
			if(res->ctrl == EXP_NODE_CTRL_BREAK){
				exp_node_destroy(res);
				res = NULL;
				break;
			}else if(res->ctrl == EXP_NODE_CTRL_CONTINUE){

			}else if(res->ctrl == EXP_NODE_CTRL_RETURN){
				break;
			}
			exp_node_destroy(res);
			res = NULL;

			var = next;
		}
	}

exit:

	exp_node_destroy(value);
	if(res){
		return res;
	}else{
		return exp_node_create(EXP_NODE_TYPE_CONST_NULL,NULL);
	}
}

exp_node_t *include_func(TFly_list_t *args, script_stack_t *block_stack,void *param)
{
	if(args == NULL || block_stack == NULL){
		return NULL;
	}

	script_t *script = TFly_list_get_first(args);
	exp_node_t *inc_name_exp = TFly_list_get_next(args);
	exp_node_t *var_name = TFly_list_get_next(args);

	script_exec_block_t *block = script_stack_get(block_stack,0);
	if(block == NULL){
		return NULL;
	}

	exp_node_t *inc_name = expression_calc(inc_name_exp,block_stack);
	exp_node_type_e type;
	char *file_name = NULL;
	get_exp_node_value(inc_name,&type,&file_name,NULL,NULL);
	if(file_name == NULL){
		SCRIPT_DEBUG_ERR("include file name calc fail!");
		return NULL;
	}

	script_include_t *inc = script_include_create(file_name);
	if(inc == NULL){
		return NULL;
	}

	include_data_t *data = script_include_data_generate(inc,block);

	exp_var_t *var = script_var_find(block_stack,var_name->var_name);
	if(var == NULL){
		goto create_new;
	}

	exp_node_t *inc_var = expression_calc(var_name,block_stack);
	if(inc_var == NULL || inc_var->type == EXP_NODE_TYPE_ERR){
		create_new:
		{
			script_exec_block_t *c_block = script_stack_Top(block_stack);
			//SCRIPT_DEBUG_ERR("ignore above error!");
			data->var_name = script_string_dump(var_name->var_name);
			exp_var_t *v = exp_var_create(var_name->string);
			v->type = EXP_VAR_TYPE_POINT;
			v->var = exp_var_refer(data->block->vars);
			exp_var_struct_add(c_block->vars,v);
		}
	}else if(inc_var->type == EXP_NODE_TYPE_VAR){
		data->var_name = script_string_dump(inc_var->var->name);
		exp_node_t *right = exp_node_create(EXP_NODE_TYPE_VAR,exp_var_refer(data->block->vars));
		extern exp_node_t *refer(exp_node_t *left, exp_node_t *right);
		exp_node_t *result = refer(inc_var,right);

		exp_node_destroy(right);
		exp_node_destroy(result);

		exp_node_destroy(inc_var);

	}

	exp_node_destroy(inc_name);



	TFly_list_add(script->includes,data);

	return exp_node_create(EXP_NODE_TYPE_VAR,exp_var_refer(data->block->vars));
}

enum{
	KEYWORD_CFUNC_VAR,
	KEYWORD_CFUNC_IF,
	KEYWORD_CFUNC_WHILE,
	KEYWORD_CFUNC_RETURN,
	KEYWORD_CFUNC_BREAK,
	KEYWORD_CFUNC_CONTINUE,
	KEYWORD_CFUNC_FOR,
	KEYWORD_CFUNC_INCLUDE,
};
const static c_func_t keyword_cfuncs[] = {
	{"var",create_var,NULL},
	{"if",if_func,NULL},
	{"while",while_func,NULL},
	{"return",sn_return,NULL},
	{"break",sn_break,NULL},
	{"continue",sn_continue,NULL},
	{"for",for_func,NULL},
	{"include",include_func,NULL}
};

const static struct script_keyword_t keywords[] = {
	{"var",		var_parse,NULL,			{EXEC_FUNC_TYPE_C,&keyword_cfuncs[KEYWORD_CFUNC_VAR]} },
	{"func",	script_func_parse,NULL	},
	{"include", include_parse,include_destroy,		{EXEC_FUNC_TYPE_C,&keyword_cfuncs[KEYWORD_CFUNC_INCLUDE]}		},
	{"if",		if_parse,if_destroy,	{EXEC_FUNC_TYPE_C,&keyword_cfuncs[KEYWORD_CFUNC_IF]} },
	{"elif",	elif_parse,if_destroy,	{EXEC_FUNC_TYPE_C,&keyword_cfuncs[KEYWORD_CFUNC_IF]} },
	{"else",	else_parse,if_destroy,	{EXEC_FUNC_TYPE_C,&keyword_cfuncs[KEYWORD_CFUNC_IF]} },
	{"while",	while_parse,if_destroy,	{EXEC_FUNC_TYPE_C,&keyword_cfuncs[KEYWORD_CFUNC_WHILE]} },
	{"return",  return_parse,NULL,		{EXEC_FUNC_TYPE_C,&keyword_cfuncs[KEYWORD_CFUNC_RETURN]} },
	{"break",	break_parse,NULL,		{EXEC_FUNC_TYPE_C,&keyword_cfuncs[KEYWORD_CFUNC_BREAK]} },
	{"continue",continue_parse,NULL,	{EXEC_FUNC_TYPE_C,&keyword_cfuncs[KEYWORD_CFUNC_CONTINUE]} },
	{"for",		for_parse,for_destroy,			{EXEC_FUNC_TYPE_C,&keyword_cfuncs[KEYWORD_CFUNC_FOR]}},
};

const struct script_keyword_t *find_keyword(char *str)
{
	const struct script_keyword_t *key;
	int i;
	int len = sizeof(keywords)/sizeof(keywords[0]);
	for(i = 0; i < len; i++){
		key = keywords+i;
		if(strcmp(key->key,str) == 0){
			return key;
		}
	}
	return NULL;
}

const struct script_keyword_t *find_keyword_by_func(void *func)
{
	const struct script_keyword_t *key;
	int i;
	int len = sizeof(keywords)/sizeof(keywords[0]);
	for(i = 0; i < len; i++){
		key = keywords+i;
		if(func == &key->keyword_func){
			return key;
		}
	}
	return NULL;
}
